package com.hs.jhzd.utils;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DateUtils {

    public static final String NUMBER = "^(([0-1]\\d)|(2[0-4])):[0-5]\\d$";

    private static final String MONTH_FORMAT = "yyyyMM";

    private static final String DATE_FORMAT = "yyyy-MM-dd";

    public static final String DATE_FORMAT2 = "yyyyMMdd";

    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String DATE_TIME_FORMAT2 = "yyyyMMddHHmmss";

    private static final String DATE_MINUTE_FORMAT = "yyyy-MM-dd HH:mm";

    private static final String DATE_PATTERN = "\\d{4}(-\\d\\d){2}";

    private static final String DATE_TIME_PATTERN = "\\d{4}(-\\d\\d){2} \\d\\d(:\\d\\d){2}";

    private static final String DATE_PATTERN2 = "\\d{8}";

    private static final String DATE_TIME_PATTERN2 = "\\d{14}";

    private static final String MONTH_PATTERN = "\\d{6}";

    private static final String DATE_MINUTE_PATTERN = "\\d{4}(-\\d\\d){2} \\d\\d:\\d\\d";

    private static final SimpleDateFormat SHORTSDF = new SimpleDateFormat(DATE_FORMAT);

    private static final SimpleDateFormat LONGSDF = new SimpleDateFormat(DATE_TIME_FORMAT);


    public static String geiTime() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT2);
        return sdf.format(d);
    }

    /**
     * 获取当前时间之前x日的00:00:00.
     *
     * @param day 应为负数
     * @return the date
     */
    public static Date minus(int day) {
        if (day == 1) {
            day = 0;
        }
        day = -day;
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, day);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * Adds the.
     *
     * @param day the day
     * @return the date
     */
    public static Date add(int day) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, day);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取昨日时间.
     *
     * @return 昨日时间
     */
    public static Date getYesterday() {
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, -1);
        return cal.getTime();

    }

    /**
     * 过去6个月得日期.
     *
     * @param date the date
     * @return the last 6 date
     */
    public static Date getLast6Date(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, -6);
        return cal.getTime();

    }

    /**
     * 开始，结束时间有多少个月份.
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return the months
     * @throws ParseException the parse exception
     */
    public static List<Date> getMonths(Date startDate, Date endDate) throws ParseException {

        List<Date> result = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");// 格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(sdf.parse(sdf.format(startDate)));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(sdf.parse(sdf.format(endDate)));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 1);
        max.add(Calendar.WEEK_OF_MONTH, -4);
        Calendar curr = min;
        while (curr.before(max)) {
            result.add(curr.getTime());
            curr.add(Calendar.MONTH, 1);
        }
        return result;
    }

    /**
     * 比较年份月份是否相等.
     *
     * @param d1 the d 1
     * @param d2 the d 2
     * @return true, if successful
     */
    public static boolean sameDate(Date d1, Date d2) {
        if (null == d1 || null == d2) {
            return false;
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(d1);
        cal1.set(Calendar.HOUR_OF_DAY, 0);
        cal1.set(Calendar.MINUTE, 0);
        cal1.set(Calendar.SECOND, 0);
        cal1.set(Calendar.MILLISECOND, 0);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(d2);
        cal2.set(Calendar.HOUR_OF_DAY, 0);
        cal2.set(Calendar.MINUTE, 0);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
        return cal1.getTime().equals(cal2.getTime());
    }

    /**
     * 获取本周的周一.
     *
     * @return 本周周一的date
     */
    public static Date getMondayOfWeek() {
        Calendar calendar = Calendar.getInstance();
        int week = calendar.get(Calendar.DAY_OF_WEEK);
        if (1 == week) {
            week = -6;
        } else {
            week = 2 - week;
        }
        calendar.add(Calendar.DAY_OF_MONTH, week);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取本周周末.
     *
     * @return 本周周末
     */
    public static Date getSundayOfWeek() {
        Calendar calendar = Calendar.getInstance();
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if (dayOfWeek == 0) {
            dayOfWeek = 7;
        }
        calendar.add(Calendar.DATE, -dayOfWeek + 7);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    /**
     * 获取当月第一天.
     *
     * @param date 时间
     * @return 当月第一天
     */
    public static Date getStartOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.MONDAY, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DATE));
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();

    }

    /**
     * 获取当月第一天.
     *
     * @param date 时间
     * @return 当月第一天
     */
    public static Date getStartOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DATE));
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();

    }

    /**
     * 获取当月最后一天.
     *
     * @param date 时间
     * @return 当月最后一天
     */
    public static Date getEndOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();

    }

    /**
     * 获取一天开始.
     *
     * @param date 时间
     * @return 一天开始时间（00:00:00）
     */
    public static Date getStartOfDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();

    }

    /**
     * 获取一天结束.
     *
     * @param date 时间
     * @return 一天结束时间（23:59:59）
     */
    public static Date getEndOfDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();

    }

    /**
     * 求出两个date相隔的秒数.
     *
     * @param from 开始时间
     * @param to   结束时间
     * @return 两个date相隔的时间。单位：秒
     */
    public static int getDifference(Date from, Date to) {
        if (from == null || to == null) {
            return -1;
        }
        Double result = Math.ceil((from.getTime() - to.getTime()) / 1000.0);
        return result.intValue();
    }

    /**
     * 秒数格式化为 hh:mm:ss.
     *
     * @param totalSecond 总秒数
     * @return 格式化后的时间字符串
     */
    public static String formatSecond(int totalSecond) {
        DecimalFormat dff = new DecimalFormat("00");
        int hour = totalSecond / (60 * 60);
        int min = (totalSecond - (hour * 60 * 60)) / 60;
        int second = totalSecond % 60;
        return dff.format(hour) + ":" + dff.format(min) + ":" + dff.format(second);
    }

    /**
     * add day.
     *
     * @param date origin date
     * @param day  add day
     * @return date
     */
    public static Date addDay(Date date, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, day);
        return cal.getTime();
    }

    /**
     * 获取本周 周几的日期.
     *
     * @param week 星期几
     * @return 日期
     */
    public static Date getWeekDay(int week) {
        Calendar cal = Calendar.getInstance();
        if (week == 7) {
            cal.add(Calendar.DATE, 7);
        }
        week = week + 1;
        cal.set(Calendar.DAY_OF_WEEK, week);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取月份的天数.
     *
     * @param date 当前时间
     * @return 当前时间是本月的第几天
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 把字符串转为date.
     *
     * @param date 时间字符串
     * @return date
     */
    public static Date string2Date(String date) {
        if (Pattern.matches(DATE_PATTERN2, date)) {
            try {
                return new SimpleDateFormat(DATE_FORMAT2).parse(date);
            } catch (ParseException ex) {
                log.error("日期转换失败:\n", ex.fillInStackTrace());
                return null;
            }
        } else if (Pattern.matches(MONTH_PATTERN, date)) {
            try {
                return new SimpleDateFormat(MONTH_FORMAT).parse(date);
            } catch (ParseException ex) {
                log.error("日期转换失败:\n", ex.fillInStackTrace());
                return null;
            }
        } else if (Pattern.matches(DATE_TIME_PATTERN2, date)) {
            try {
                return new SimpleDateFormat(DATE_TIME_FORMAT2).parse(date);
            } catch (ParseException ex) {
                log.error("日期转换失败:\n", ex.fillInStackTrace());
                return null;
            }
        } else if (Pattern.matches(DATE_PATTERN, date)) {
            try {
                return new SimpleDateFormat(DATE_FORMAT).parse(date);
            } catch (ParseException ex) {
                log.error("日期转换失败:\n", ex.fillInStackTrace());
                return null;
            }
        } else if (Pattern.matches(DATE_TIME_PATTERN, date)) {
            try {
                return new SimpleDateFormat(DATE_TIME_FORMAT).parse(date);
            } catch (ParseException ex) {
                log.error("日期转换失败:\n", ex.fillInStackTrace());
                return null;
            }
        } else if (Pattern.matches(DATE_MINUTE_PATTERN, date)) {
            try {
                return new SimpleDateFormat(DATE_MINUTE_FORMAT).parse(date);
            } catch (ParseException ex) {
                log.error("日期转换失败:\n", ex.fillInStackTrace());
                return null;
            }
        } else if (StringUtils.isNumeric(date)) {
            return new Date(Long.parseLong(date));
        }
        return null;

    }

    /**
     * 当前季度的开始时间，即2012-01-1 00:00:00.
     *
     * @return 时间
     */
    public static Date getCurrentQuarterStartTime() {
        Calendar c = Calendar.getInstance();
        int currentMonth = c.get(Calendar.MONTH) + 1;
        Date now = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 3) {
                c.set(Calendar.MONTH, 0);
            } else if (currentMonth >= 4 && currentMonth <= 6) {
                c.set(Calendar.MONTH, 3);
            } else if (currentMonth >= 7 && currentMonth <= 9) {
                c.set(Calendar.MONTH, 6);

            } else if (currentMonth >= 10 && currentMonth <= 12) {
                c.set(Calendar.MONTH, 9);
                c.set(Calendar.DATE, 1);
            }
            now = LONGSDF.parse(SHORTSDF.format(c.getTime()) + " 00:00:00");
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return now;
    }

    /**
     * 当前季度的结束时间，即2012-03-31 23:59:59.
     *
     * @return 时间
     */
    public static Date getCurrentQuarterEndTime() {
        Calendar c = Calendar.getInstance();
        int currentMonth = c.get(Calendar.MONTH) + 1;
        Date now = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 3) {
                c.set(Calendar.MONTH, 2);
                c.set(Calendar.DATE, 31);
            } else if (currentMonth >= 4 && currentMonth <= 6) {
                c.set(Calendar.MONTH, 5);
                c.set(Calendar.DATE, 30);
            } else if (currentMonth >= 7 && currentMonth <= 9) {
                c.set(Calendar.MONTH, 8);
                c.set(Calendar.DATE, 30);
            } else if (currentMonth >= 10 && currentMonth <= 12) {
                c.set(Calendar.MONTH, 11);
                c.set(Calendar.DATE, 31);
            }
            now = LONGSDF.parse(SHORTSDF.format(c.getTime()) + " 23:59:59");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return now;
    }

    /**
     * Parses the time string.
     *
     * @param dateStr the date str
     * @return the date
     */
    public static Date parseTimeString(String dateStr) {
        if (StringUtils.length(dateStr) < 8) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        if (StringUtils.length(dateStr) == 8) {
            calendar.set(Integer.parseInt(dateStr.substring(0, 4)),
                    Integer.parseInt(dateStr.substring(4, 6)), Integer.parseInt(dateStr.substring(6, 8)));
        } else if (StringUtils.length(dateStr) == 14) {
            calendar.set(Integer.parseInt(dateStr.substring(0, 4)),
                    Integer.parseInt(dateStr.substring(4, 6)), Integer.parseInt(dateStr.substring(6, 8)),
                    Integer.parseInt(dateStr.substring(8, 10)), Integer.parseInt(dateStr.substring(10, 12)),
                    Integer.parseInt(dateStr.substring(12, 14)));
        }
        return calendar.getTime();
    }

    /**
     * Gets the days.
     *
     * @param startDate the start date
     * @param endDate   the end date
     * @return the days
     */
    public static List<Date> getDays(Date startDate, Date endDate) {

        List<Date> result = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// 格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        try {
            min.setTime(sdf.parse(sdf.format(startDate)));
            max.setTime(sdf.parse(sdf.format(endDate)));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), min.get(Calendar.DAY_OF_MONTH));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), max.get(Calendar.DAY_OF_MONTH));
        max.add(Calendar.DAY_OF_MONTH, 1);
        Calendar curr = min;
        while (curr.before(max)) {
            result.add(curr.getTime());
            curr.add(Calendar.DAY_OF_MONTH, 1);
        }
        return result;
    }

    /**
     * Interval times.
     *
     * @param begintime the begintime
     * @param endtime   the endtime
     * @param minute    the minute
     * @return the int
     */
    public static int intervalTimes(String begintime, String endtime, int minute) {
        Pattern pattern = Pattern.compile(NUMBER);
        Matcher matcher = pattern.matcher(begintime);
        if (!matcher.matches()) {
            return 0;
        }
        matcher = pattern.matcher(endtime);
        if (!matcher.matches()) {
            return 0;
        }
        String[] unitsBegin = begintime.split(":");
        int hoursBegin = Integer.parseInt(unitsBegin[0]);
        int minutesBegin = Integer.parseInt(unitsBegin[1]);
        int durationBegin = hoursBegin * 3600 + minutesBegin * 60;

        String[] unitsEnd = endtime.split(":");
        int hoursEnd = Integer.parseInt(unitsEnd[0]);
        int minutesEnd = Integer.parseInt(unitsEnd[1]);
        if (hoursEnd < hoursBegin) {
            hoursEnd = hoursEnd + 24;
        }
        int durationEnd = hoursEnd * 3600 + minutesEnd * 60 + minute * 60;

        int result = 0;
        result = ((durationEnd - durationBegin) / 60) / minute;
        return result;
    }

    /**
     * Adds the minute.
     *
     * @param time   the time
     * @param minute the minute
     * @return the string
     */
    public static String addMinute(String time, int minute) {
        String timeStr = "";
        Pattern pattern = Pattern.compile(NUMBER);
        Matcher matcher = pattern.matcher(time);
        if (!matcher.matches()) {
            return timeStr;
        }
        String[] units = time.split(":");
        int hours = Integer.parseInt(units[0]);
        int minutes = Integer.parseInt(units[1]);
        int duration = hours * 3600 + minutes * 60 + minute * 60;
        timeStr = secToTime(duration);
        return timeStr;
    }

    /**
     * Sec to time.
     *
     * @param time the time
     * @return the string
     */
    public static String secToTime(int time) {
        String timeStr = null;
        int hour = 0;
        int minute = 0;
        if (time <= 0) {
            return "00:00";

        } else {
            minute = time / 60;
            if (minute < 60) {
                timeStr = unitFormat(hour) + ":" + unitFormat(minute);
            } else {
                hour = minute / 60;
                if (hour >= 24) {
                    hour = 0;
                }
                minute = minute % 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute);
            }
        }
        return timeStr;
    }

    /**
     * Unit format.
     *
     * @param i the i
     * @return the string
     */
    public static String unitFormat(int i) {
        String retStr = null;
        if (i >= 0 && i < 10) {
            retStr = "0" + Integer.toString(i);
        } else {
            retStr = "" + i;
        }
        return retStr;
    }

    /**
     * Format shift time.
     *
     * @param startTime the start time
     * @param endTime   the end time
     * @param timeSpan  the time span
     * @return the string
     */
    public static String formatShiftTime(String startTime, String endTime, Integer timeSpan) {
        Pattern pattern = Pattern.compile(NUMBER);
        Matcher startMatcher = pattern.matcher(startTime);
        Matcher endMatcher = pattern.matcher(endTime);
        if (!startMatcher.matches() || !endMatcher.matches()) {
            return "";
        }
        String[] startUnits = startTime.split(":");
        String[] endUnits = endTime.split(":");
        String dateStr = "";
        if (Integer.parseInt(startUnits[0]) < Integer.parseInt(endUnits[0])) {
            if (StringUtils.endsWith(endUnits[0], "24")) {
                endUnits[0] = "0";
            }
            if (StringUtils.endsWith(startUnits[0], "24")) {
                startUnits[0] = "0";
            }
            dateStr = "01,16,31,46 " + startUnits[0] + "-" + endUnits[0] + " * * *";
        } else {
            dateStr = "01,16,31,46 " + startUnits[0] + "-23,0-" + endUnits[0] + " * * *";
        }

        // if (Integer.parseInt(startUnits[0]) < Integer.parseInt(endUnits[0])) {
        // sDate = "*/5 * * * *";
        // } else {
        // sDate = "*/5 * * * *";
        // }
        return dateStr;

    }

    public static String formatShiftTime(String startTime) {
        Pattern pattern = Pattern.compile(NUMBER);
        Matcher startMatcher = pattern.matcher(startTime);
        if (!startMatcher.matches()) {
            return "";
        }
        String[] startUnits = startTime.split(":");
        return startUnits[1] + " " + startUnits[0] + " * * *";
    }


    /**
     * 获取某年某月的第一天
     *
     * @throws
     * @Title:getFisrtDayOfMonth
     * @Description:
     * @param:@param year
     * @param:@param month
     * @param:@return
     * @return:String
     */
    public static Date getFisrtDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最小天数
        int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最小天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        //格式化日期
        Date time = cal.getTime();
        return time;
    }

    public static Date getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        Date time = cal.getTime();
        return time;
    }
    /**
     * The main method.
     *
     * @param args the arguments
     * @throws ParseException the parse exception
     */

}
